// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.network.packets.hit;

import java.nio.ByteBuffer;
import java.util.Optional;
import zombie.characters.IsoGameCharacter;
import zombie.core.network.ByteBufferWriter;
import zombie.core.raknet.UdpConnection;
import zombie.network.GameServer;
import zombie.network.packets.INetworkPacket;

public abstract class Character extends Instance implements IPositional, INetworkPacket {
    protected IsoGameCharacter character;
    protected short characterFlags;
    protected float positionX;
    protected float positionY;
    protected float positionZ;
    protected float directionX;
    protected float directionY;
    protected String characterReaction;
    protected String playerReaction;
    protected String zombieReaction;

    public void set(IsoGameCharacter _character) {
        super.set(_character.getOnlineID());
        this.characterFlags = 0;
        this.characterFlags = (short)(this.characterFlags | (short)(_character.isDead() ? 1 : 0));
        this.characterFlags = (short)(this.characterFlags | (short)(_character.isCloseKilled() ? 2 : 0));
        this.characterFlags = (short)(this.characterFlags | (short)(_character.isHitFromBehind() ? 4 : 0));
        this.characterFlags = (short)(this.characterFlags | (short)(_character.isFallOnFront() ? 8 : 0));
        this.characterFlags = (short)(this.characterFlags | (short)(_character.isKnockedDown() ? 16 : 0));
        this.characterFlags = (short)(this.characterFlags | (short)(_character.isOnFloor() ? 32 : 0));
        this.character = _character;
        this.positionX = _character.getX();
        this.positionY = _character.getY();
        this.positionZ = _character.getZ();
        this.directionX = _character.getForwardDirection().getX();
        this.directionY = _character.getForwardDirection().getY();
        this.characterReaction = (String)Optional.ofNullable(_character.getHitReaction()).orElse("");
        this.playerReaction = (String)Optional.ofNullable(_character.getVariableString("PlayerHitReaction")).orElse("");
        this.zombieReaction = (String)Optional.ofNullable(_character.getVariableString("ZombieHitReaction")).orElse("");
    }

    @Override
    public void parse(ByteBuffer b, UdpConnection connection) {
        super.parse(b, connection);
        this.characterFlags = b.getShort();
        this.positionX = b.getFloat();
        this.positionY = b.getFloat();
        this.positionZ = b.getFloat();
        this.directionX = b.getFloat();
        this.directionY = b.getFloat();
        this.characterReaction = zombie.GameWindow.ReadString(b);
        this.playerReaction = zombie.GameWindow.ReadString(b);
        this.zombieReaction = zombie.GameWindow.ReadString(b);
    }

    @Override
    public void write(ByteBufferWriter b) {
        super.write(b);
        b.putShort(this.characterFlags);
        b.putFloat(this.positionX);
        b.putFloat(this.positionY);
        b.putFloat(this.positionZ);
        b.putFloat(this.directionX);
        b.putFloat(this.directionY);
        b.putUTF(this.characterReaction);
        b.putUTF(this.playerReaction);
        b.putUTF(this.zombieReaction);
    }

    @Override
    public boolean isConsistent() {
        return super.isConsistent() && this.character != null;
    }

    @Override
    public String getDescription() {
        return super.getDescription()
            + "\n\tCharacter [ hit-reactions=( \"c=\""
            + this.characterReaction
            + "\" ; p=\""
            + this.playerReaction
            + "\" ; z=\""
            + this.zombieReaction
            + "\" ) | "
            + this.getFlagsDescription()
            + " | pos=( "
            + this.positionX
            + " ; "
            + this.positionY
            + " ; "
            + this.positionZ
            + " ) | dir=( "
            + this.directionX
            + " ; "
            + this.directionY
            + " ) | health="
            + (this.character == null ? "?" : this.character.getHealth())
            + " | current="
            + (this.character == null ? "?" : "\"" + this.character.getCurrentActionContextStateName() + "\"")
            + " | previous="
            + (this.character == null ? "?" : "\"" + this.character.getPreviousActionContextStateName() + "\"")
            + " ]";
    }

    String getFlagsDescription() {
        return " Flags [ isDead="
            + ((this.characterFlags & 1) != 0)
            + " | isKnockedDown="
            + ((this.characterFlags & 16) != 0)
            + " | isCloseKilled="
            + ((this.characterFlags & 2) != 0)
            + " | isHitFromBehind="
            + ((this.characterFlags & 4) != 0)
            + " | isFallOnFront="
            + ((this.characterFlags & 8) != 0)
            + " | isOnFloor="
            + ((this.characterFlags & 32) != 0)
            + " ]";
    }

    void process() {
        this.character.setHitReaction(this.characterReaction);
        this.character.setVariable("PlayerHitReaction", this.playerReaction);
        this.character.setVariable("ZombieHitReaction", this.zombieReaction);
        this.character.setCloseKilled((this.characterFlags & 2) != 0);
        this.character.setHitFromBehind((this.characterFlags & 4) != 0);
        this.character.setFallOnFront((this.characterFlags & 8) != 0);
        this.character.setKnockedDown((this.characterFlags & 16) != 0);
        this.character.setOnFloor((this.characterFlags & 32) != 0);
        if (GameServer.bServer && (this.characterFlags & 32) == 0 && (this.characterFlags & 4) != 0) {
            this.character.setFallOnFront(true);
        }
    }

    protected void react() {
    }

    @Override
    public float getX() {
        return this.positionX;
    }

    @Override
    public float getY() {
        return this.positionY;
    }

    public abstract IsoGameCharacter getCharacter();
}
